#!/usr/bin/env python
# coding=UTF-8
import random
import logging
import json
import time
import datetime
import copy
import urllib
import config
import dao

from nsq.http import nsqd
import redisco
from redisco.containers import List, Hash
import itertools
from tools import nsq_pub, json_encode


class HZMaJiangCheck():
    def __init__(self):
        self._res = []
        self.joker_list = []
    
    def all_combination(self, all_card, card, joker_list=[]):
        c_1 = card - 1
        c_2 = card - 2
        c1 = card + 1
        c2 = card + 2
        res = []
        if all_card.count(card) >= 2:
            res.append([card, card])
        if card < 40:
            j_n = len(joker_list)
            if c1 % 10 <= 8 and c2%10 <=9 and c2/10 == card/10:
                if c1 in all_card and c2 in all_card:
                    res.append([c1, c2])
                elif c1 in all_card and j_n >= 1:
                    res.append([c1, joker_list[0]])
                elif c2 in all_card and j_n >= 1:
                    res.append([c2, joker_list[0]])
            if c_1 % 10 >0 and c1 % 10 <=9 and c_1/10 == card/10 and c1/10==card/10:
                if c1 in all_card and c_1 in all_card:
                    res.append([c_1, c1])
                elif c1 in all_card and j_n >= 1:
                    res.append([c1, joker_list[0]])
                elif c_1 in all_card and j_n >= 1:
                    res.append([c_1, joker_list[0]])
            if c_1 % 10 >0 and c_2 % 10 >0 and c_2/10 == card/10 and c_1/10==card/10:
                if c1 in all_card and c_1 in all_card:
                    res.append([c_1, c_2])
                elif c1 in all_card and j_n >= 1:
                    res.append([c_1, joker_list[0]])
                elif c_1 in all_card and j_n >= 1:
                    res.append([c_2, joker_list[0]])
            
        if all_card.count(card) == 1 and len(joker_list) >= 1:
            res.append([card, joker_list[0]])
        elif len(joker_list) >= 2:
            res.append([joker_list[0], joker_list[1]])
        return res
    
    def card_group(self, all_card, pre='', joker_list=[]):
        card_list = self.trans_card(all_card)
        if not card_list:
            return self._res
        c = card_list.pop(0)
        all_group = self.all_combination(card_list, c, joker_list)
        if not all_group:
            return self.card_group(card_list, pre, joker_list)
        for group in all_group:
            tmp = pre
            card_copy = copy.deepcopy(card_list)
            joker_copy = copy.deepcopy(joker_list)
            g1 = group[0]
            g2 = group[1]
            if g1 in card_copy:
                card_copy.remove(g1)
            elif g1 in joker_copy:
                joker_copy.remove(g1)
            else:
                break
            if g2 in card_copy:
                card_copy.remove(g2)
            elif g2 in joker_copy:
                joker_copy.remove(g2)
            else:
                break
            
            tmp += "%s,%s,%s_" % (c, g1, g2)
            self._res.append(tmp)
            self.card_group(card_copy, tmp, joker_copy)
        return self._res
        
    def card_group_merge(self, all_card):
        card_list = self.trans_card(all_card)
        tmp_result = []
        for group in self._res:
            if group.endswith("_"):
                group = group[:-1]
            rows = group.split("_")
            if len(rows) > len(tmp_result):
                tmp_result = rows
        res = []
        for row in tmp_result:
            seq = []
            for x in row.split(","):
                if int(x) in card_list:
                    card_list.remove(int(x))
                seq.append(int(x))
            res.append(seq)
        self._res = []
        return res, card_list

    def trans_card(self, all_card):
        return sorted([int(x) for x in all_card])
    
    def get_jiang(self, card, joker_list=[]):
        r = []
        for k in set(card):
            if card.count(k) >= 2 or joker_list:
                r.append(k)
        r.sort()
        return r
    
    def count_group(self, all_card, jiang):
        n = 0
        res = []
        card_list = self.trans_card(all_card)
        j_n = card_list.count(jiang)
        if j_n < 2:
            if len(self.joker_list) < 2 - j_n:
                return 0, []
            for i in range(j_n):
                card_list.remove(jiang)
            for i in range((2-j_n)):
                self.joker_list.pop()
        else:
            card_list.remove(jiang)
            card_list.remove(jiang)
        n += 1
        left_card = []
        card_list.sort()
        joker_list = copy.deepcopy(self.joker_list)
        self.card_group(card_list, '', joker_list)
        seq, left_card = self.card_group_merge(card_list)
        n += len(seq)
        return n, left_card
    
    def check_win(self, n, current_card, card='', joker=[]):
        if card:
            current_card.append(card)
        current_card = self.trans_card(current_card)
        joker = self.trans_card(joker)
        joker_list = []
        for j in joker:
            j_n = current_card.count(j)
            joker_list.extend([j]*j_n)
            for i in range(j_n):
                current_card.remove(j)
        jiang_list = self.get_jiang(current_card, joker_list)
        for jiang in jiang_list:
            all_joker = copy.deepcopy(joker_list)
            self.joker_list = all_joker
            allcard = self.trans_card(current_card)
            group_n, left_card = self.count_group(allcard, jiang)
            if not left_card and group_n + n >= 6:
                return True
        return False

    def is_jinque(self, n, current_card, card='', joker=[]):
        if card:
            current_card.append(card)
        current_card = self.trans_card(current_card)
        joker = self.trans_card(joker)
        joker_list = []
        for j in joker:
            j_n = current_card.count(j)
            joker_list.extend([j]*j_n)
            for i in range(j_n):
                current_card.remove(j)
        if len(joker_list) < 2:
            return False
        all_joker = copy.deepcopy(joker_list)
        self.joker_list = all_joker
        allcard = self.trans_card(current_card)
        group_n, left_card = self.count_group(allcard, all_joker[0])
        if not left_card and group_n + n >= 6:
            return True
        return False
    
def get_last_data(bid, uid, rid):
    all_player_data = []
    mj = FuZhouMaJiang(rid, bid)
    for member in mj.members:
        p = Player(member, bid, rid)
        player_data = p.get_data()
        eat_list = []
        eat_data_list = player_data['eat']
        for eat_data in eat_data_list:
            eat_list.append(eat_data.split(","))
        player_data['eat'] = eat_list
        player_data['status'] = 1
        all_player_data.append(player_data)
    game_round = mj.room['game_round']
    all_round = mj.room['all_round']
    dealer = mj.room['dealer']
    status = mj.room['status']
    last_get_user = mj.room['last_get_user']
    last_put_user = mj.room['last_put_user']
    if last_put_user:
        last_player = last_put_user
    else:
        last_player = last_get_user
    last_card = mj.room['last_card']
    left_card = len(mj.current_card.members)
    joker = mj.room['joker']
    pub_data = {"act":"get_last_data",
                "game_round":game_round, 
                "all_round":all_round, 
                "last_card":last_card, 
                "last_player":last_player,
                "left_card":left_card,
                "dealer":dealer,
                "status":status,
                "rid":rid,
                "joker":joker,
                "all_player_data":all_player_data,
                }
    nsq_pub({"b":bid, "u":uid, "t":"game", "d":pub_data})
    tips_user = mj.tips_user
    if tips_user:
        if uid in tips_user:
            p = Player(uid, bid, rid)
            tips = p.tips.members
            eat_card_list = []
            bar_card = []
            if "dark_bar" in tips:
                bar_card = mj.check_init_dark_bar(p.current_card.members)
            elif "eat" in tips:
                eat_card_list = mj.get_eat_card(p.current_card.members, last_card)
            mj.notify_tips(uid, last_card, tips, bar_card, eat_card_list)
    else:
        nsq_pub({"b":bid, "u":uid, "t":"game", "d":{"act":"turn_put", "rid":rid, "uid":last_player}})

class Player():
    def __init__(self, uid, bid='', rid='', first=False):
        self.uid = uid
        self.bid = bid
        self.rid = rid
        if first:
            redisco.connection.delete("p:%s:%s:%s:current_card" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:out_card" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:dark_bar" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:white_bar" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:pair" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:eat" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:flower" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:tips" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:bar_user" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:pair_bar_user" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s" % (bid, uid, rid))
            self.score = Hash("p:%s:%s:%s" % (bid, uid, rid))
            self.score['score'] = 0
            self.score['win_score'] = 0
            self.score['put_flag'] = ''
            self.score['win_type'] = ''
            self.score['win_type_name'] = ''
            self.score['win_card'] = ''
        else:
            self.score = Hash("p:%s:%s:%s" % (bid, uid, rid))
        self.current_card = List("p:%s:%s:%s:current_card" % (bid, uid, rid))
        self.out_card = List("p:%s:%s:%s:out_card" % (bid, uid, rid))
        self.dark_bar = List("p:%s:%s:%s:dark_bar" % (bid, uid, rid))
        self.white_bar = List("p:%s:%s:%s:white_bar" % (bid, uid, rid))
        self.pair = List("p:%s:%s:%s:pair" % (bid, uid, rid))
        self.eat = List("p:%s:%s:%s:eat" % (bid, uid, rid))
        self.flower = List("p:%s:%s:%s:flower" % (bid, uid, rid))
        self.tips = List("p:%s:%s:%s:tips" % (bid, uid, rid))
        self.bar_user = List("p:%s:%s:%s:bar_user" % (bid, uid, rid))
        self.pair_bar_user = List("p:%s:%s:%s:pair_bar_user" % (bid, uid, rid))

    def clear(self):
        redisco.connection.delete("p:%s:%s:%s:current_card" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:out_card" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:dark_bar" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:white_bar" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:pair" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:eat" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:flower" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:tips" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:bar_user" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:pair_bar_user" % (self.bid, self.uid, self.rid))

    def get_data(self):
        return {"uid":self.uid,
                "current_card":self.current_card.members,
                "out_card":self.out_card.members,
                "dark_bar":self.dark_bar.members,
                "white_bar":self.white_bar.members,
                "pair":self.pair.members,
                "eat":self.eat.members,
                "flower":self.flower.members,
                "score":self.score['score'],
                }
        
class FuZhouMaJiang():
    def __init__(self, rid, bid, dealer=None):
        self.rid = str(rid)
        self.bid = bid
        if dealer:
            redisco.connection.delete("r:%s:current_card" % rid)
            redisco.connection.delete("r:%s:out_card" % rid)
            redisco.connection.delete("r:%s:mid" % rid)
            redisco.connection.delete("r:%s:tips_user" % rid)
            redisco.connection.delete("r:%s:tips_act" % rid)
            redisco.connection.delete("r:%s:winner" % rid)
            self.room = Hash("r:%s" % rid)
            self.room['dealer'] = dealer
            self.room['last_get_user'] = dealer
            self.room['last_put_user'] = ''
            self.room['stop_pop_user'] = ''
            self.room['stop_pop_act'] = ''
            self.room['loser'] = ''
            self.room['last_card'] = ''
            self.room['joker'] = ''
        else:
            self.room = Hash("r:%s" % rid)
        self.current_card = List("r:%s:current_card" % rid)
        self.out_card = List("r:%s:out_card" % rid)
        self.tips_user = List("r:%s:tips_user" % rid)
        self.tips_act = List("r:%s:tips_act" % rid)
        self.winner = List("r:%s:winner" % rid)
        l = List("r:%s:p" % rid)
        self.members = l.members

    def incr_mid(self):
        return redisco.connection.incr("r:%s:mid" % self.rid)
    
    def trans_card(self, all_card):
        res = []
        for c in all_card:
            res.append(int(c))
        res.sort()
        return res

    def get_jiang(self, all_card):
        res = []
        card = self.trans_card(all_card)
        for c in set(card):
            if card.count(c) >= 2:
                res.append(c)
        return res
    
    def get_n(self, all_card, jiang, joker=[]):
        n = 0
        res = []
        jiang = int(jiang)
        card = self.trans_card(all_card)
        card.sort()
        if jiang and card.count(jiang) >= 2:
            card.remove(jiang)
            card.remove(jiang)
            n += 1
        while card:
            c = card.pop(0)
            if card.count(c) >= 2:
                n += 1
                card.remove(c)
                card.remove(c)
                res.append([c, c, c])
            elif c > 400:
                break
            else:
                c2 = c + 1
                c3 = c + 2
                if c2 in card and c3 in card:
                    card.remove(c2)
                    card.remove(c3)
                    res.append([c, c2, c3])
                    n += 1
                else:
                    break
        return n
    
    def is_pinghu(self, all_card, has_n=0, win_type='put_win', joker_list=[]):
        '''平胡'''
        mj = HZMaJiangCheck()
        res = mj.check_win(has_n, all_card, '', joker_list)
        if res:
            return 'pinghu'
        return False
    
    def is_sanjindao(self, current_card, joker_list):
        '''三金倒'''
        n = 0
        for j in joker_list:
            j_n = current_card.count(j)
            n += j_n
        if n >= 3:
            return True
        return False
    
    def is_qingyise(self, all_card):
        '''清一色:240'''
        card = self.trans_card(all_card)
        color = card[0]/100
        for c in set(card):
            if c/100 != color:
                return False
        return 'qingyise'
    
    def is_jingque(self, current_card, n, joker_list):
        all_card = self.trans_card(current_card)
        joker_card = self.trans_card(joker_list)
        for j in joker_card:
            j_n = all_card.count(j)
            for i in range(j_n):
                all_card.remove(j)
        mj = HZMaJiangCheck()
        res = mj.is_jinque(n, all_card, '', joker_card)
        if res:
            return 'jinque'
        return False
    
    def is_jinglong(self, current_card, n, joker_list):
        all_card = self.trans_card(current_card)
        joker_card = self.trans_card(joker_list)
        j_count = 0
        for j in joker_card:
            j_n = all_card.count(j)
            j_count += j_n
            for i in range(j_n):
                all_card.remove(j)
        if j_count == 3:
            mj = HZMaJiangCheck()
            res = mj.check_win(n+1, all_card, '', [])
            if res:
                return 'jinlong'
        return False
    
    def is_yizhanghua(self, member_player):
        '''一张花'''
        if len(member_player.flower.members) == 1:
            return 'yizhanghua'
        return False
    
    def is_wuhuawugang(self, member_player):
        '''无花无杠'''
        flower = member_player.flower.members
        dark_bar = member_player.dark_bar.members
        white_bar = member_player.white_bar.members
        if not (flower and dark_bar and white_bar):
            return 'wuhuawugang'
        return False
    
    def check_init_dark_bar(self, current_card):
        # 检查初始手牌能否暗杠
        res = []
        for k in set(current_card):
            if current_card.count(k) == 4:
                res.append(k)
        return res
    
    def check_dark_bar(self, current_card, card=''):
        # 检查摸的牌能否暗杠
        if current_card.count(card) == 4:
            return True
        return False

    def check_bar(self, current_card, card=''):
        # 检查能否杠
        if current_card.count(card) == 3:
            return True
        return False

    def check_pair_bar(self, pair, card=''):
        # 检查碰过的牌是否摸到杠
        if pair.count(card) >= 1:
            return True
        return False
    
    def check_pair(self, current_card, card=''):
        # 检查能否碰牌
        if current_card.count(card) >= 2:
            return True
        return False
    
    def check_win(self, player, card=''):
        '''检查是否符合自模糊'''
        # 检查
        n = 0
        dark_bar = player.dark_bar.members
        white_bar = player.white_bar.members
        pair = player.pair.members
        eat = player.eat.members
        n += len(dark_bar)
        n += len(white_bar)
        n += len(pair)
        n += len(eat)
        current_card = player.current_card.members
        if card:
            current_card.append(card)
        joker = self.room['joker']
        if joker:
            joker_list = joker.split(",")
        else:
            joker_list = []
        logging.info(u"判断用户%s是否胡牌:%s" % (player.uid, str(current_card)))
        if len(current_card) != ((4 - n) * 3 + 2):
            logging.info(u"该玩家手牌相公不能胡牌:%s" % player.uid)
            return False
        elif self.is_sanjindao(player.current_card.members, joker_list):
            return True
        elif self.is_pinghu(current_card, n, 'win', joker_list):
            return True
        return False
    
    def get_win_score(self, win_type_list):
        score = 0
        win_type_conf = {                
                        'qingyise':{'name':u"清一色", 'score':240},
                         'qixiaodui':{'name':u"混一色", 'score':120},
                         'jinlong':{'name':u"金龙", 'score':120},
                         'jinque':{'name':u"金雀", 'score':60},
                         'sanjindao':{'name':u"三金倒", 'score':40},
                         'yizhanghua':{'name':u"一张花", 'score':30},
                         'wuhuawugang':{'name':u"无花无杠", 'score':30},
                         'qiangjin':{'name':u"抢金", 'score':30},
                         'tianhu':{'name':u"天胡", 'score':30},
                         'pinghu':{'name':u"自模胡", 'score':2},
                         'put_pinghu':{'name':u"接炮胡", 'score':1},
                         }
        win_type = win_type_list[0]
        return win_type_conf[win_type]['score']
    
    def trans_win_type(self, win_type_list):
        res = []
        win_type_conf = {
                        'qingyise':{'name':u"清一色", 'score':240},
                         'qixiaodui':{'name':u"混一色", 'score':120},
                         'jinlong':{'name':u"金龙", 'score':120},
                         'jinque':{'name':u"金雀", 'score':60},
                         'sanjindao':{'name':u"三金倒", 'score':40},
                         'yizhanghua':{'name':u"一张花", 'score':30},
                         'wuhuawugang':{'name':u"无花无杠", 'score':30},
                         'qiangjin':{'name':u"抢金", 'score':30},
                         'tianhu':{'name':u"天胡", 'score':30},
                         'pinghu':{'name':u"自模胡", 'score':2},
                         'put_pinghu':{'name':u"接炮胡", 'score':1},
                         }
        for win_type in win_type_list:
            res.append(win_type_conf[win_type]['name'])
        return res
    
    def get_win_type(self, player, card='', win_type='win'):
        n = 0
        dark_bar = player.dark_bar.members
        white_bar = player.white_bar.members
        pair = player.pair.members
        eat = player.eat.members
        n += len(dark_bar)
        n += len(white_bar)
        n += len(pair)
        n += len(eat)
        current_card = player.current_card.members
        if card:
            current_card.append(card)
        if len(current_card) != ((4 - n) * 3 + 2):
            logging.info(u"该玩家手牌相公不能胡牌:%s" % player.uid)
            return False
        
        joker = self.room['joker']
        if joker:
            joker_list = joker.split(",")
        else:
            joker_list = []
        pinghu = self.is_pinghu(current_card, n, win_type, joker_list)
        if not pinghu:
            sanjindao = self.is_sanjindao(current_card, joker_list)
            if sanjindao:
                return [sanjindao]
            return False
        all_card = []
        all_card.extend(current_card)
        if dark_bar:
            all_card.extend(dark_bar)
        if white_bar:
            all_card.extend(white_bar)
        if pair:
            all_card.extend(pair)
        if eat:
            for eat_card in eat:
                all_card.extend(eat_card.split(","))
        qingyise = self.is_qingyise(all_card)
        if qingyise:
            if self.is_pinghu(current_card, n, win_type, []):
                return ['qingyise',]
            return ['hunyise',]
        jinlong = self.is_jinglong(current_card, n, joker_list)
        if jinlong:
            return [jinlong]
        jinque = self.is_jingque(current_card, n, joker_list)
        if jinque:
            return [jinque]
        yizhanghua = self.is_yizhanghua(player)
        if yizhanghua:
            return [yizhanghua]
        wuhuawugang = self.is_wuhuawugang(player)
        if wuhuawugang:
            return [wuhuawugang]
        if win_type == 'win':
            return ['pinghu']
        return ['put_pinghu']
            
    def get_eat_card(self, all_card, card):
        '''获取可吃的牌'''
        card = int(card)
        if card > 400:
            return []
        c = card % 100
        n = card / 100
        res = []
        point_res = []
        if c == 9:
            point_res = [[7, 8]]
        elif c == 8:
            point_res = [[6, 7], [7, 9]]
        elif c == 7:
            point_res = [[5, 6], [6, 8], [8, 9]]
        elif c == 6:
            point_res = [[4, 5], [5, 7], [7, 8]]
        elif c == 5:
            point_res = [[3, 4], [4, 6], [6, 7]]
        elif c == 4:
            point_res = [[2, 3], [3, 5], [5, 6]]
        elif c == 3:
            point_res = [[1, 2], [2, 4], [4, 5]]
        elif c == 2:
            point_res = [[1, 3], [3, 4]]
        elif c == 1:
            point_res = [[2, 3]]
        for [s, e] in point_res:
            c1 = str(n*100+s)
            c2 = str(n*100+e)
            if c1 in all_card and c2 in all_card:
                res.append([c1, c2])
        return res
    
    def check_eat(self, all_card, card):
        '''判断能否吃card牌'''
        card = int(card)
        all_card = [int(x) for x in all_card]
        all_card.append(card)
        all_card.sort()
        if len(all_card) == 3 and (all_card[0]+1) == all_card[1] and (all_card[0]+2) == all_card[2]:
            return True
        return False
    
    def all_flower(self, all_card):
        res = []
        for c in all_card:
            if int(c) > 400:
                res.append(c)
        return res
    
    def sub_flower(self, dealer):
        dealer_seat = self.members.index(dealer)
        player_cnt = len(self.members)
        while 1:
            need = False
            for i in range(player_cnt):
                idex = (dealer_seat + i) % player_cnt
                member = self.members[idex]
                member_player = Player(member, self.bid, self.rid)
                member_all_card = member_player.current_card.members
                flower_card = self.all_flower(member_all_card)
                if flower_card:
                    new_card = self.do_sub_flower(member, flower_card)
                    if self.all_flower(new_card):
                        need = True
            if not need:
                break
    
    def do_sub_flower(self, uid, flower_card=[]):
        member_player = Player(uid, self.bid, self.rid)
        member_player.flower.extend(flower_card)
        new_card = []
        for c in flower_card:
            member_player.current_card.remove(c, 1)
            card = self.current_card.pop()
            new_card.append(card)
        member_player.current_card.extend(new_card)
        all_flower = member_player.flower.members
        current_card = member_player.current_card.members
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"sub_flower", "rid":self.rid, "uid":uid, "all_flower_num":len(all_flower), "all_flower":all_flower, "flower":flower_card, "new_card":new_card, "current_card":current_card}})
        return new_card
            
    def pub_joker(self, dealer):
        dealer_player = Player(dealer, self.bid, self.rid)
        while 1:
            c = self.current_card.members[0]
            if int(c) > 400:
                c = self.current_card.shift()
                dealer_player.flower.append(c)
                all_flower = dealer_player.flower.members
                current_card = dealer_player.current_card.members
                flower_card = [c]
                for member in self.members:
                    nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"get_flower", "rid":self.rid, "uid":dealer, "all_flower_num":len(all_flower), "all_flower":all_flower, "flower":flower_card, "new_card":[], "current_card":current_card}})
            else:
                break
            
        self.room['joker'] = c
        c_16 = self.current_card[16]
        self.current_card[0] = c_16
        self.current_card[16] = c
        #开金的牌放在倒数第九墩上(也就是第17张牌)
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"pub_joker", "joker":c, "rid":self.rid}})
    
    def notify_put(self, uid):
        '''通知玩家出牌'''
        self.room['last_get_user'] = uid
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"turn_put", "rid":self.rid, "uid":uid}})
    
    def notify_tips(self, uid, card, tips, bar_card=[], eat_card=[]):
        #self.room['stop_pop_user'] = ""
        #self.room['stop_pop_act'] = ""
        nsq_pub({"b":self.bid, "u":str(uid), "t":"game", "d":{"act":"tips", "rid":self.rid, "uid":uid, "tips":tips, "card":card, "bar_card":bar_card, "eat_card":eat_card}})
    
    def start(self):
        self.room['status'] = 'start'
        w = [str(x) for x in range(101, 110)] * 4
        d = [str(x) for x in range(201, 210)] * 4
        t = [str(x) for x in range(301, 310)] * 4
        f = [str(x) for x in range(401, 408)] * 4
        h = [str(x) for x in range(501, 509)]
        random.shuffle(w)
        random.shuffle(d)
        random.shuffle(t)
        random.shuffle(f)
        random.shuffle(h)
        player_cnt = len(self.members)
        init_left_card = 144 - player_cnt * 16 - 1
        all_card = w + d + t + f + h
        random.shuffle(all_card)
        
        game_type = self.room['game_type']
        dealer = self.room['dealer']
        game_round = self.room['game_round']
        all_round = self.room['all_round']
        dealer_seat = self.members.index(dealer)
        all_user_card = []
        for i in range(player_cnt):
            idex = (dealer_seat + i) % player_cnt
            uid = self.members[idex]
            player = Player(uid, self.bid, self.rid, True)
            card = []
            if i == 0:
                for i in range(17):
                    card.append(all_card.pop())
            else:
                for i in range(16):
                    card.append(all_card.pop())
            card.sort()
            all_user_card.append({"uid":uid, "current_card":card})
            player.current_card.clear()
            player.current_card.extend(card)
            
        mid = self.incr_mid()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"game_start", "left_card":init_left_card, "rid":self.rid, "dealer":dealer, "game_round":game_round, "all_round":all_round, "all_user_card":all_user_card}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"game_start", "game_round":game_round,"left_card":init_left_card, "rid":self.rid, "mid":mid, "dealer":dealer, "game_round":game_round, "all_round":all_round, "all_user_card":all_user_card}})
        
        self.room['last_get_user'] = dealer
        self.current_card.clear()
        self.current_card.extend(all_card)
        logging.info(u"房间rid:%s,game_round:%s,发牌结束" % (self.rid, self.room['game_round']))
        
        #补花
        self.sub_flower(dealer)
        #开金
        self.pub_joker(dealer)
        
        p = Player(dealer, self.bid, self.rid)
        win_flag = self.check_win(p, '')
        if win_flag:
            tips = ['win']
            win_card = p.current_card.members[-1]
            
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
            self.tips_user.append(dealer)
            self.tips_act.extend(tips)
            p.tips.extend(tips)
            self.notify_tips(dealer, win_card, tips, [], [])
        else:
            self.notify_put(dealer)

    def next_pop(self, uid=None, from_bar=False):
        # 发牌逻辑
        self.tips_act.clear()
        self.tips_user.clear()
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        if not uid:
            last_get_user = self.room['last_get_user']
            logging.info("next_pop, last:%s" % last_get_user)
            last_player_seat = self.members.index(str(last_get_user))
            idx = (last_player_seat + 1) % len(self.members)
            uid = self.members[idx]
        
        left_card = len(self.current_card.members)
        horse_num = int(self.room['horse'])
        if left_card <= horse_num:
            logging.info(u"房间%s剩余牌数小于马牌数量，结束牌局" % (left_card, horse_num))
            self.game_over()
            return
        card = self.current_card.pop()
        if not card:
            logging.info("over===========")
            self.game_over()
            return
        
        p = Player(uid, self.bid, self.rid)
        flower_card = self.all_flower([card])
        if flower_card:
            p.flower.extend(flower_card)
            for c in flower_card:
                p.current_card.remove(c, 1)
            all_flower = p.flower.members
            for member in self.members:
                nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"get_flower", "rid":self.rid, "uid":uid, "all_flower_num":len(all_flower), "all_flower":all_flower, "flower":flower_card}})
            self.next_pop(uid, from_bar)
            return
        
        self.room['last_get_user'] = uid
        self.room['last_card'] = card
        if from_bar:
            self.room['bar_get_card'] = card
        else: 
            self.room['bar_get_card'] = ''
            
        p.tips.clear()
        #检查漏胡标记, 摸牌后清除状态
        p_flag = p.score['flag']
        if p_flag == 'n':
            p.score['flag'] = ''
        tips = []
        bar_card = []
        win_type = self.check_win(p, card)
        if win_type:
            tips.append("win")
        
        current_card = p.current_card.members
        init_dark_bar = self.check_init_dark_bar(current_card)
        if self.check_bar(current_card, card):
            tips.append("dark_bar")
            bar_card.append(card)
        elif self.check_pair_bar(p.pair.members, card):
            tips.append("pair_bar")
            
        if init_dark_bar:
            tips.append("dark_bar")
            bar_card.extend(init_dark_bar)
        user_data = p.get_data()
        p.current_card.append(card)
        
        mid = self.incr_mid()
        left_card = len(self.current_card)
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"get_card", "left_card":left_card, "uid":uid, "card":card, "rid":self.rid}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"get_card", "game_round":game_round,"left_card":left_card, "mid":mid, "uid":uid, "card":card, "rid":self.rid, "user_data":user_data}})
        
        if tips:
            self.tips_user.append(uid)
            self.tips_act.extend(tips)
            p.tips.extend(tips)
            self.notify_tips(uid, card, tips, bar_card)
        else:
            self.notify_put(uid)
            
    def put_card(self, uid, data):
        # 玩家出牌逻辑
        uid = str(uid)
        #是否重复发牌给客户端
        stop_pop_user = self.room['stop_pop_user']
        if stop_pop_user and stop_pop_user != str(uid):
            logging.error(u"玩家:%s有提示未处理,轮不到%s出牌" % (stop_pop_user, uid))
            get_last_data(self.bid, uid, self.rid)
            return
        last_put_user = self.room['last_put_user']
        if uid == last_put_user:
            logging.error(u"玩家:%s不能连续出牌" % (uid))
            get_last_data(self.bid, uid, self.rid)
            return
        card = data['card']
        p = Player(uid, self.bid, self.rid)
        curernt_card = p.current_card.members
        if curernt_card.count(card) == 0:
            logging.info(curernt_card)
            logging.error(u"出牌错误,该玩家没有该牌")
            get_last_data(self.bid, uid, self.rid)
            return
        
        #self.tips_act.clear()
        #self.tips_user.clear()
        
        p.out_card.append(card)
        p.current_card.remove(card)
        self.room['last_put_user'] = uid
        self.room['last_get_user'] = uid
        self.room['last_card'] = card
        dealer = self.room['dealer']
        put_flag = p.score['put_flag']
        
        
        p.score['put_flag'] = 'y'
        members = self.members
        player_cnt = len(members)
        mid = self.incr_mid()
        put_win_user = []
        #按照玩家座位顺序检查是否有胡牌可能
        user_seat = members.index(uid)
        tips = []
        self.room['bar_get_card'] = ''
        user_data = p.get_data()
        for i in range(player_cnt):
            idex = (user_seat + i) % player_cnt
            member = members[idex]
            win_card = []
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"put_card", "win_card":win_card, "card":card, "rid":self.rid, "uid":uid}})

        if uid == dealer and not put_flag:
            #庄家第一次出牌后执行抢金
            joker = self.room['joker']
            for i in range(player_cnt):
                idex = (user_seat + i) % player_cnt
                member = members[idex]
                if member != uid:
                    member_player = Player(member, self.bid, self.rid)
                    if self.check_win(member_player, joker):
                        put_win_user.append(member)
                        member_player.tips.append("put_win")
            if put_win_user:
                #点炮胡的情况
                self.room['stop_pop_user'] = ""
                self.room['stop_pop_act'] = ""
                tips = ["put_win",]
                self.tips_user.extend(put_win_user)
                self.tips_act.extend(tips)
                for win_user in put_win_user:
                    self.notify_tips(win_user, card, tips, [], [])
                return
        
        for i in range(player_cnt):
            idex = (user_seat + i) % player_cnt
            member = members[idex]
            if member != uid:
                member_player = Player(member, self.bid, self.rid)
                if self.check_win(member_player, card):
                    put_win_user.append(member)
                    member_player.tips.append("put_win")
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"put_card", "game_round":game_round,"win_card":win_card, "mid":mid, "card":card, "rid":self.rid, "uid":uid, "user_data":user_data}})
        
        if put_win_user:
            #点炮胡的情况
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
            tips = ["put_win",]
            self.tips_user.extend(put_win_user)
            self.tips_act.extend(tips)
            for win_user in put_win_user:
                self.notify_tips(win_user, card, tips, [], [])
            return
        
        tips_user = self.check_put_tips(uid, card)
        if tips_user:
            return
        #所有提示都没有的情况,继续下家发牌
        self.next_pop()
        
        
    def check_put_tips(self, last_put_user='', card=''):
        if not last_put_user:
            last_put_user = self.room['last_put_user']
            last_put_player = Player(last_put_user, self.bid, self.rid)
            card = last_put_player.out_card.members[-1]
        
        members = self.members
        user_seat = members.index(last_put_user)
        next_idex = (user_seat + 1) % len(members)
        next_member = members[next_idex]
        tips_user = []
        eat_card_list = []
        for member in members:
            if member != last_put_user:
                member_player = Player(member, self.bid, self.rid)
                current_card = member_player.current_card.members
                tips = [] 
                if self.check_bar(current_card, card):
                    tips.append("bar")
                    tips.append("pair")
                elif self.check_pair(current_card, card):
                    tips.append("pair")
                
                if member == next_member:
                    eat_card_list = self.get_eat_card(current_card, card)
                    if eat_card_list:
                        tips.append("eat")
                else:
                    eat_card_list = []

                if tips:
                    tips_user.append(member)
                    self.tips_user.append(member)
                    self.tips_act.extend(tips)
                    member_player.tips.extend(tips)
                    self.notify_tips(member, card, tips, [], eat_card_list)
                    logging.info(u"房间%s玩家%s出牌%s,%s通知提示" % (self.rid, last_put_user, card, member))
        if tips_user:
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
        return tips_user
    
    def pass_card(self, uid, data):
        logging.info(u"有玩家pass:%s" % uid)
        tips_user = self.tips_user.members
        if uid not in tips_user:
            logging.error(u"房间:%s该用户没有提示操作不能pass:%s" % (self.rid, uid))
            return
        
        self.tips_user.remove(uid)
        p = Player(uid, self.bid, self.rid)
        p.tips.clear()
        if len(tips_user) - 1 == 0:
            tips_act = self.tips_act.members
            self.tips_act.clear()
            
            top_tips_user = self.room['stop_pop_user']
            if top_tips_user:
                #执行高优先级的操作
                top_tips_act = self.room['stop_pop_act']
                if 'put_win' == top_tips_act:
                    self.game_over()
                    return
                elif 'pair_bar_win' == top_tips_act:
                    self.game_over()
                    return
                elif 'eat' == top_tips_act:
                    top_player = Player(top_tips_user, self.bid, self.rid)
                    eat_data = json.loads(top_player.score['eat_data'])
                    self.do_eat(top_tips_user, eat_data)
                    return
                return
            else:
                if "win" in tips_act or "dark_bar" in tips_act or "pair_bar" in tips_act:
                    logging.info(u"房间%s 玩家%s摸牌后放弃操作:%s" % (self.rid, uid, str(tips_act)))
                    self.notify_put(uid)
                    return
                elif "put_win" in tips_act:
                    logging.info(u"房间%s put_win玩家%s全部都放弃杠后放炮胡牌,检查有无碰或杠或吃" % (self.rid, uid))
                    tips_user = self.check_put_tips()
                    if tips_user:
                        return
                    else:
                        if self.winner:
                            self.game_over()
                        else:
                            self.next_pop()
                elif "pair_bar_win" in tips_act:
                    logging.info(u"房间%s玩家%s全部都放弃pair_bar_win" % (self.rid, uid))
                    if self.winner:
                        self.game_over()
                    else:
                        last_get_user = self.room['last_get_user']
                        self.next_pop(last_get_user, from_bar=True)
                else:
                    self.next_pop()
        else:
            logging.info(u"房间:%s玩家%s pass, 等待其他玩家处理" % (self.rid, uid ))


    def dark_bar(self, uid, data):
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        
        card = data.get('card', '')
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if not card:
            for k in set(current_card):
                if current_card.count(k) == 4:
                    card = k
        else:
            if not self.check_dark_bar(current_card, card):
                logging.error(u"请求错误,该用户不能杠牌:%s" % card)
                get_last_data(self.bid, uid, self.rid)
                return
        p.current_card.remove(card, 4)
        p.dark_bar.append(card)
        
        p.tips.clear()
        self.tips_user.clear()
        self.tips_act.clear()
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        mid = self.incr_mid()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"dark_bar", "card":card, "tips":[], "rid":self.rid, "uid":uid}})
        user_data = p.get_data()
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"dark_bar", "game_round":game_round,"mid":mid, "card":card, "tips":[], "rid":self.rid, "uid":uid, "user_data":user_data}})
        
        self.next_pop(uid)
        
    def pair_bar(self, uid, data):
        # 碰过别的牌, 然后自己摸到一张，杠没有分
        # card = data['card']
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return

        p = Player(uid, self.bid, self.rid)
        card = p.current_card.members[-1]
        if not self.check_pair_bar(p.pair.members, card):
            logging.error(u"请求错误,该用户不能杠牌:%s" % card)
            get_last_data(self.bid, uid, self.rid)
            return
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        p.current_card.remove(card)
        p.pair.remove(card)
        p.white_bar.append(card)
        
        p.pair_bar_user.append(uid)
        p.tips.clear()
        self.tips_user.clear()
        self.tips_act.clear()
        
        self.room['last_get_user'] = uid
        self.room['last_card'] = card
        mid = self.incr_mid()
        tips = []
        user_data = p.get_data()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"pair_bar", "card":card, "tips":[], "rid":self.rid, "uid":uid}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"pair_bar", "game_round":game_round,"mid":mid, "card":card, "tips":[], "rid":self.rid, "uid":uid, "user_data":user_data}})
        bar_win_user = []
        for member in self.members:
            if member != uid:
                member_player = Player(member, self.bid, self.rid)
                tips = []
                if self.room['grab_bar_win'] == 'y':
                    if self.check_win(member_player, card):
                        bar_win_user.append(member)
        
        if bar_win_user:
            #点炮胡的情况
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
            tips = ["pair_bar_win"]
            self.tips_user.extend(bar_win_user)
            self.tips_act.extend(tips)
            for win_user in bar_win_user:
                self.notify_tips(win_user, card, tips, [], [])
            return
        else:
            self.next_pop(uid, from_bar=True)
    
    def bar(self, uid, data):
        # 自己有三张,直接杠别人出的牌
        # card = data['card']
        # bar_uid = data['put_card_uid']
        
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        
        card = last_put_player.out_card.members[-1]
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if not self.check_bar(current_card, card):
            logging.error(u"请求错误,该用户不能杠牌:%s" % card)
            get_last_data(self.bid, uid, self.rid)
            return
        p.score['put_flag'] = 'y'
        card = last_put_player.out_card.pop()
        p.current_card.remove(card, 3)
        p.white_bar.append(card)
        p.bar_user.append(last_put_user)
        
        p.tips.clear()
        self.tips_user.clear()
        self.tips_act.clear()
        mid = self.incr_mid()
        self.room['last_get_user'] = uid
        self.room['last_card'] = card
        user_data = p.get_data()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"bar", "card":card, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user, "user_data":{}}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"bar", "game_round":game_round,"mid":mid, "card":card, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user, "user_data":user_data}})
        
        bar_win_user = []
        for member in self.members:
            if member != uid:
                member_player = Player(member, self.bid, self.rid)
                tips = []
                if member in tips_user:
                    member_player.tips.clear()
                if self.room['grab_bar_win'] == 'y':
                    if self.check_win(member_player, card):
                        bar_win_user.append(member)
        
        if bar_win_user:
            #点炮胡的情况
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
            tips = ["pair_bar_win"]
            self.tips_user.extend(bar_win_user)
            self.tips_act.extend(tips)
            for win_user in bar_win_user:
                self.notify_tips(win_user, card, tips, [], [])
            return
        else:
            self.next_pop(uid, from_bar=True)

    def pair(self, uid, data):
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        # card = data['card']
        # put_card_uid = data['put_card_uid']
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if not self.check_pair(current_card, card):
            logging.error(u"请求错误,该用户不能碰牌:%s" % card)
            get_last_data(self.bid, uid, self.rid)
            return
        card = last_put_player.out_card.pop()
        p.score['put_flag'] = 'y'
        p.current_card.remove(card, 2)
        p.pair.append(card)
        
        self.tips_user.clear()
        self.tips_act.clear()
        p.tips.clear()
        
        user_data = p.get_data()
        mid = self.incr_mid()
        for member in self.members:
            if member in tips_user:
                member_player = Player(member, self.bid, self.rid)
                member_player.tips.clear()
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"pair", "card":card, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user, "user_data":{}}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"pair", "game_round":game_round, "mid":mid, "card":card, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user, "user_data":user_data}})
        self.room['last_get_user'] = uid
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        self.notify_put(uid)


    def eat(self, uid, data):
        '''吃牌'''
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        eat_card_list = self.get_eat_card(current_card, card)
        if not eat_card_list:
            logging.error(u"请求错误,该用户不能吃这张牌:%s" % card)
            get_last_data(self.bid, uid, self.rid)
            return
        if len(tips_user) > 1:
            p.score['eat_data'] = json_encode(data)
            self.room['stop_pop_user'] = uid
            self.room['stop_pop_act'] = "eat"
            return
        p.tips.clear()
        
        self.do_eat(uid, data)
    
    def do_eat(self, uid, data):
        '''吃牌'''
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        eat_card_list = self.get_eat_card(current_card, card)
        if not eat_card_list:
            logging.error(u"请求错误,该用户不能吃这张牌:%s" % card)
            get_last_data(self.bid, uid, self.rid)
            return
        
        eat_card = data['eat_card']
        c1 = eat_card[0]
        c2 = eat_card[1]
        if c1 not in current_card or c2 not in current_card or not self.check_eat(eat_card, card):
            logging.error(u"吃牌错误,该用户%s不能吃这张牌:%s" % (uid, card))
            get_last_data(self.bid, uid, self.rid)
            return
        self.tips_user.clear()
        self.tips_act.clear()
        
        card = last_put_player.out_card.pop()
        p.current_card.remove(eat_card[0], 1)
        p.current_card.remove(eat_card[1], 1)
        p.score['put_flag'] = 'y'
        eat_card_list = [c1, c2, card]
        eat_card_list.sort()
        p.eat.append(",".join(eat_card_list))
        mid = self.incr_mid()
        user_data = p.get_data()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"eat", "card":card, "eat_card":eat_card_list, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user, "user_data":{}}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"eat", "game_round":game_round,"mid":mid, "card":card, "eat_card":eat_card_list, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user, "user_data":user_data}})
        
        self.room['last_get_user'] = uid
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        self.notify_put(uid)
        
    def win(self, uid, data):
        if self.room['status'] != 'start':
            logging.error(u"该轮游戏已结束")
            return
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        card = current_card[-1]
        p.tips.clear()
        
        if not self.check_win(p, ''):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            get_last_data(self.bid, uid, self.rid)
            return
        
        self.winner.append(uid)
        
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        
        member_len = len(self.members)
        win_type_list = self.get_win_type(p, '')
        
        score = self.get_win_score(win_type_list)
        win_type_list = self.trans_win_type(win_type_list)
        #base_score = 1
        flower_score = self.get_flower_score(p.flower.members)
        joker_score = self.get_joker_score(current_card)
        bar_score = 2*len(p.dark_bar)+len(p.white_bar)
        win_score = score + 2*(flower_score+joker_score+bar_score)
        
        p.score['win_score'] = win_score
        p.score['win_type'] = 'win'
        p.score['win_type_name'] = u" ".join(win_type_list)
        p.score['win_card'] = card
        logging.info(u"用户%s自摸胡牌" % (uid))
        mid = self.incr_mid()
        user_data = p.get_data()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"win", "card":card, "rid":self.rid, "uid":uid, "user_data":{}}})
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"win", "game_round":game_round,"mid":mid, "card":card, "rid":self.rid, "uid":uid, "user_data":user_data}})
        
        self.game_over(uid, card)
        
    def put_win(self, uid, data):
        #点炮胡
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        logging.info("last_put_user:%s, card:%s" % (last_put_user, card))
        p = Player(uid, self.bid, self.rid)
        if not self.check_put_win(p, card):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            return
        
        self.winner.append(uid)
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        all_horse_card = []
        data['card'] = card
        win_type_list = self.get_put_win_type(p, card)
        logging.info(u"点炮胡:%s" % str(win_type_list))
        members = self.members
        score = self.get_win_score(win_type_list)
        win_score = score
        logging.info(u"房间:%s用户%s点炮胡" % (self.rid, uid))
        win_type_list = self.trans_win_type(win_type_list)
        logging.info(u"点炮胡:%s" % str(win_type_list))
        #grab_bar_duty = self.room['grab_bar_duty']
        p.score['win_score'] = win_score
        p.score['win_type'] = 'put_win'
        p.score['win_type_name'] = u" ".join(win_type_list)
        p.score['win_card'] = card
        self.room['loser'] = last_put_user
        user_data = p.get_data()
        mid = self.incr_mid()
        for member in members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"win", "mid":mid, "card":card, "rid":self.rid, "uid":uid, "user_data":{}}})
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"win", "game_round":game_round, "mid":mid, "card":card, "rid":self.rid, "uid":uid, "user_data":user_data}})
        if len(self.winner.members) == len(tips_user):
            self.game_over()
    
    def pair_bar_win(self, uid, data={}):
        # 抢杠胡,杠家全包,退还之前杠的分数
        tips_user = self.tips_user.members
        tips_act = self.tips_act.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        elif 'pair_bar_win' not in tips_act:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        
        #card = data['card']
        bar_uid = self.room['last_get_user']
        bar_player = Player(bar_uid, self.bid, self.rid)
        white_bar_member = bar_player.white_bar.members
        if white_bar_member:
            card = white_bar_member[-1]
        else:
            card = data.get("card", "")
        p = Player(uid, self.bid, self.rid)
        if not self.check_win(p, card):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            return
        
        self.winner.append(uid)
        win_type_list = self.get_win_type(p, card)
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        score = self.get_win_score(win_type_list)
        member_len = len(self.members)
        every_lose_score = score
        win_score = every_lose_score * (member_len - 1)
        win_type_list = self.trans_win_type(win_type_list)
        logging.info(u"用户%s抢杠胡,得%s分" % (uid, win_score))
        p.score['win_score'] = win_score
        p.score['win_type'] = 'pair_bar_win'
        p.score['win_type_name'] = u" ".join(win_type_list)
        p.score['win_card'] = card
        self.room['loser'] = bar_uid
        
        user_data = p.get_data()
        mid = self.incr_mid()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"win", "mid":mid, "card":card, "rid":self.rid, "uid":uid, "user_data":{}}})
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"win", "game_round":game_round, "mid":mid, "card":card, "rid":self.rid, "uid":uid, "user_data":{}}})
        if len(self.winner.members) == len(tips_user):
            self.game_over()

    def game_over(self, from_dissmiss=False):
        all_horse_card = []
        horse_card = []
        horse_num = 0
        winner_list = self.winner.members
        horse = 0
        horse_score = 0 
        #计算每个玩家的分数
        all_players = {}
        for member in self.members:
            member_player = Player(member, self.bid, self.rid)
            all_players[member] = member_player
        if winner_list:
            if len(winner_list) > 1:
                #抢杠或点炮
                loser = self.room['loser']
                #loser_player = Player(loser, self.bid, self.rid)
                loser_player = all_players[loser]
                for winner in winner_list:
                    winner_player = Player(winner, self.bid, self.rid)
                    win_score = int(winner_player.score['win_score']) + horse_score
                    loser_player.score['score'] = int(loser_player.score['score']) - win_score*3
            else:
                winner = winner_list[0]
                #winner_player = Player(winner, self.bid, self.rid)\
                winner_player = all_players[winner]
                win_type = winner_player.score['win_type']
                win_score = int(winner_player.score['win_score']) + horse_score
                winner_player.score['score'] = win_score * 3
                if win_type  == 'win':
                    #自摸三家扣钱
                    for member in self.members:
                        if member != winner:
                            #member_player = Player(member, self.bid, self.rid)
                            member_player = all_players[member]
                            member_player.score['score'] = int(member_player.score['score']) - win_score
                else:
                    #抢杠或点炮的点炮者包其他三家
                    loser = self.room['loser']
                    loser_player = Player(loser, self.bid, self.rid)
                    loser_player.score['score'] = int(loser_player.score['score']) - win_score*3
            
        self.room['status'] = 'over'
        self.room['stop_pop_user'] = ''
        self.room['stop_pop_act'] = ''
        self.room['last_put_user'] = ''
        self.room['last_get_user'] = ''
        game_round = int(self.room['game_round'])
        all_round = int(self.room['all_round'])
        
        dealer = self.room['dealer']
        if len(winner_list)>1:
            self.room['dealer'] = self.room['loser']
        elif len(winner_list) == 1:
            self.room['dealer'] = winner_list[0]
        
        room_left_card = len(self.current_card.members)
        gid = self.room['gid']
        match_id = self.room['mid']
        if not match_id:
            match_id = 0
        db = dao.Game_DB()
        rules = {}
        if gid:
            rows = db.game_rule(gid)
        else:
            rows = db.room_rule(self.rid)
            gid = ""
        for row in rows:
            k = row['param']
            v = row['value']
            rules[k] = v
            
        if game_round >= all_round or from_dissmiss:
            room_over = 'y'
        else:
            room_over = 'n'
        card = self.room['last_card']
        mid = self.incr_mid()
        player_card = {}
        for member in self.members:
            #member_player = Player(member, self.bid, self.rid)
            member_player = all_players[member]
            p_data = member_player.get_data()
            del p_data['out_card']
            if member in winner_list:
                p_data['is_winner'] = 'y'
                is_win = 1
            else:
                p_data['is_winner'] = 'n'
                is_win = 0
            if member == dealer:
                is_dealer = 'y'
            else:
                is_dealer = 'n'
            p_data['is_dealer'] = is_dealer
            score = int(p_data['score'])
            db.update_player(self.rid, member, score, 0)
            db.commit()
            player_info = db.get_player(self.rid, member)
            p_data['user_score'] = player_info['score']
            player_card[member] = p_data
            
            dark_bar = p_data['dark_bar']
            white_bar = p_data['white_bar']
            db.add_mj_room_log(match_id, gid, self.rid, game_round, member, score, len(white_bar), len(dark_bar), horse, is_dealer, is_win, 0, '')
            db.commit()
        
        game_type = self.room['game_type']
        game_type_name = config.GAME_TYPE_NAME[game_type]
        for member in self.members:
            pub_data = {"b":self.bid, "u":member, "t":"game", "d":{"act":"game_over", "game_type_name":game_type_name, "room_left_card":room_left_card, "gid":gid, "rules":rules, "room_over":room_over, "dealer":dealer, "game_round":game_round, "player_card":player_card, "mid":mid, "winner_list":winner_list, "rid":self.rid, "all_horse_card":all_horse_card, "horse_card":horse_card, "horse_num":horse_num}}
            nsq_pub(pub_data)
            db.save_game_over(self.rid, game_round, "game_over", member, urllib.quote(json_encode(pub_data).encode("utf-8")))
            db.commit()
            
        if room_over == 'y':
            self.dismiss()
        else:
            self.room['game_round'] = game_round + 1
            
            
    def dismiss(self, act='room_over'):
        db = dao.Game_DB()
        player_data = {}
        player_stat = []
        if not self.room['status']:
            logging.error(u"房间结束,未开始:%s" % self.rid)
            deduct_flag = False
            winner = ""
            for uid in self.members:
                player_stat.append({"uid":uid,"horse":0,"dark_bar":0,"white_bar":0,"score":0,"win_num":0, "is_best":"n"})
        else:
            p_stat = db.player_stat(self.rid)
            #logging.info(p_stat)
            for ps in p_stat:
                ps['horse'] = int(ps['horse'])
                ps['dark_bar'] = int(ps['dark_bar'])
                ps['white_bar'] = int(ps['white_bar'])
                ps['score'] = int(ps['score'])
                ps['win_num'] = int(ps['win_num'])
                ps['is_best'] = 'n'
                player_data[str(ps['uid'])] = ps
            deduct_flag = True
            if p_stat and p_stat[-1]['win_num'] > 0:
                winner = p_stat[-1]['uid']
            else:
                winner = ""
            # 排序最后一家为大赢家
            player_stat = p_stat
        
        match_id = self.room['mid']
        if not match_id:
            match_id = 0
        gid = self.room['gid']
        if not gid:
            gid = 0
        for ps in player_stat:
            if ps['uid'] == winner:
                is_best = 'y'
            else:
                is_best = 'n'
            ps['is_best'] = is_best
            if gid:
                db.add_room_stat(match_id, gid, self.rid, ps['uid'], ps['score'], is_best)
                db.commit()
            
        room_info = db.get_room(self.rid, self.bid)
        admin = room_info['admin']
        end_time = time.strftime("%Y-%m-%d %H:%M:%S")
        for member in self.members:
            if not member:
                continue
            pub_data = {"b":self.bid, "u":member, "t":"game", "d":{"act":"room_over", "rid":self.rid, "end_time":end_time, "player_stat":player_stat, "winner":winner, "admin":admin}}
            nsq_pub(pub_data)
            db.save_game_over(self.rid, 0, "room_over", member, json_encode(pub_data))
            db.commit()
        db.dismiss_room(self.rid)
        db.commit()
        game_type = self.room['game_type']
        if match_id or gid:
            nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"game_type":game_type, "match_id":match_id, "gid":gid, "act":"room_over", "rid":self.rid, "player_stat":player_stat, "winner":winner, "admin":admin}}, "match_club")
            
        if deduct_flag:
            card = room_info['card']
            db.deduct_card(self.bid, admin, card)
            nsq_pub({"act":"deduct_card", "bid":self.bid, "uid":admin, "card":card, "rid":self.rid}, "total")
            logging.info(u"房间%s解散成功,扣除房卡, bid:%s,uid:%s,card:%s" % (self.rid, self.bid, admin, card))
        else:
            logging.info(u"房间%s解散成功,游戏无需扣房卡" % self.rid)

        for member in self.members:
            member_player = Player(member, self.bid, self.rid)
            member_player.clear()
            
        redisco.connection.delete("r:%s:current_card" % self.rid)
        redisco.connection.delete("r:%s:out_card" % self.rid)
        redisco.connection.delete("r:%s" % self.rid)
        redisco.connection.delete("r:%s:mid" % self.rid)
        redisco.connection.delete("r:%s:p" % self.rid)
        redisco.connection.delete("r:%s:tips_user" % self.rid)
        redisco.connection.delete("r:%s:tips_act" % self.rid)
        redisco.connection.delete("r:%s:winner" % self.rid)
